package com.xinchao.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.xinchao.core.constant.BusinessConstant;
import com.xinchao.core.constant.DeviceSettingType;
import com.xinchao.core.constant.ModuleConstant;
import com.xinchao.core.constant.PageConstant;
import com.xinchao.core.exception.ServiceException;
import com.xinchao.core.util.BeanUtils;
import com.xinchao.core.util.FileUtils;
import com.xinchao.core.util.HuaWeiCloudUtils;
import com.xinchao.dao.DeviceSettingMapper;
import com.xinchao.dao.DeviceUpgradeMapper;
import com.xinchao.model.DeviceSetting;
import com.xinchao.model.DeviceUpgrade;
import com.xinchao.model.OperationLog;
import com.xinchao.model.User;
import com.xinchao.model.page.PageInfo;
import com.xinchao.model.vo.DeviceUpgradeListVO;
import com.xinchao.model.vo.DeviceUpgradeVO;
import com.xinchao.service.DeviceInfoService;
import com.xinchao.service.OperationLogService;
import com.xinchao.service.UpgradeService;
import net.dongliu.apk.parser.ApkFile;
import net.dongliu.apk.parser.bean.ApkMeta;
import net.dongliu.apk.parser.exception.ParserException;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.rmi.ServerException;
import java.text.DecimalFormat;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * 终端升级Service实现类
 */
@Service(value = "ckUpgradeService")
public class UpgradeServiceImpl implements UpgradeService {
	private static Logger logger = LoggerFactory.getLogger(UpgradeServiceImpl.class);
	@Autowired
	private DeviceUpgradeMapper deviceUpgradeMapper;
	@Autowired
	private OperationLogService operationLogService;
	@Autowired
	private DeviceSettingMapper deviceSettingMapper;
	@Autowired
	private DeviceInfoService deviceInfoService;

	@Autowired
	private  HuaWeiCloudUtils huaWeiCloudUtils;

	/**
	 * 保存终端升级
	 * @param deviceUpgrade DeviceUpgrade对象
	 * @param user
	 * @param operationIP
	 */
	@Override
	@Transactional(readOnly = false, rollbackFor = Exception.class)
	public void saveDeviceUpgrade(DeviceUpgrade deviceUpgrade, User user, String operationIP) {
		deviceUpgrade.setAddTime(System.currentTimeMillis());
		deviceUpgrade.setUpdateTime(System.currentTimeMillis());
		deviceUpgrade.setActive(BusinessConstant.DEVICE_UPGRADE_FORCE_NO);
		deviceUpgrade.setUploader(user.getUserName());
		deviceUpgrade.setStatus(BusinessConstant.STATUS_ENABLE);
		// 删除url最后一个字符:“,”
		String url = deviceUpgrade.getUrl();
		String endChar = ",";
		if(endChar.equals(url.substring(url.length()-1,url.length()))) {
			deviceUpgrade.setUrl(url.substring(0, url.length()-1));
		}
		deviceUpgradeMapper.saveDeviceUpgrade(deviceUpgrade);
		
		// 保存操作日志
		String module = "";
		String keywords = "";
		if ( BusinessConstant.DEVICE_UPGRADE_TYPE_FIRMWARE == deviceUpgrade.getUpgradeType() ) {
			module = ModuleConstant.MODULE_FIRMWARE_MNG;
			keywords = "添加固件：[" +deviceUpgrade.getUpgradeName() + "]";
		} else {
			module = ModuleConstant.MODULE_SOFTWARE_MNG;
			keywords = "添加APK：[" +deviceUpgrade.getUpgradeName() + "]";
		}
		saveLog(operationIP, user, keywords ,module);
	}

	/**
	 * 获取终端升级分页列表
	 * hanqr 2018-08-13
	 * @param upgradeType 升级类型(0:软件；1:固件)
	 * @param pageNum  当前页
	 * @param pageSize 每页显示条数
	 * @return PageInfo<DeviceUpgradeListVO>
	 */
	@Override
	public PageInfo<DeviceUpgradeListVO> listDeviceUpgradeByPage(Integer upgradeType, Integer pageNum, Integer pageSize) {
		pageNum = pageNum == null ? PageConstant.DEFAULT_PAGE_NUM : pageNum;
		pageSize = pageSize == null ? PageConstant.DEFAULT_PAGE_SIZE : pageSize;
		PageHelper.startPage(pageNum, pageSize);
		Page<DeviceUpgradeListVO> page = deviceUpgradeMapper.listDeviceUpgradeByPage(upgradeType);
		if (page == null) {
			return new PageInfo<>(pageNum, pageSize, 0, Lists.newArrayList());
		}
		//把Page转化为PageInfo
		PageInfo<DeviceUpgradeListVO> pageInfo = new PageInfo<>();
		pageInfo.setPageNum(pageNum);
		pageInfo.setPageSize(pageSize);
		pageInfo.setTotal(page.getTotal());
		pageInfo.setList(page.getResult());
		return pageInfo;
	}

	/**
	 * 通过ID获取终端升级
	 * @param deviceUpgradeId 终端升级ID
	 * @return TbDeviceUpgrade
	 * @throws ServerException
	 */
	@Override
	public DeviceUpgrade getDeviceUpgradeById(Long deviceUpgradeId) throws ServerException {
		if (deviceUpgradeId == null) {
			throw new ServerException("终端升级ID不能为空");
		}
		return deviceUpgradeMapper.getDeviceUpgradeById(deviceUpgradeId);
	}

	/**
	 * 更新终端升级
	 * @param deviceUpgrade 终端升级
	 * @param user 当前登录用户
	 * @param operationIp 当前操作ip
	 * @throws ServerException
	 */
	@Override
	@Transactional(readOnly = false, rollbackFor = Exception.class)
	public void updateDeviceUpgrade(DeviceUpgrade deviceUpgrade,User user,String operationIp) throws ServerException {
		DeviceUpgrade oldDeviceUpgrade = getDeviceUpgradeById(deviceUpgrade.getDeviceUpgradeId());
		// 删除url最后一个字符:“,”
		String url = deviceUpgrade.getUrl();
		String endChar = ",";
		if(endChar.equals(url.substring(url.length()-1,url.length()))) {
			deviceUpgrade.setUrl(url.substring(0, url.length()-1));
		}
		oldDeviceUpgrade.setUrl(deviceUpgrade.getUrl());
		oldDeviceUpgrade.setUpgradeName(deviceUpgrade.getUpgradeName());
		oldDeviceUpgrade.setVersionName(deviceUpgrade.getVersionName());
		oldDeviceUpgrade.setSize(deviceUpgrade.getSize());
		oldDeviceUpgrade.setMd5(deviceUpgrade.getMd5());
		oldDeviceUpgrade.setModelId(deviceUpgrade.getModelId());
		oldDeviceUpgrade.setDescription(deviceUpgrade.getDescription());
		oldDeviceUpgrade.setVersionCode(deviceUpgrade.getVersionCode());
		oldDeviceUpgrade.setUpdateTime(System.currentTimeMillis());
		oldDeviceUpgrade.setStatus(BusinessConstant.STATUS_ENABLE);
		deviceUpgradeMapper.updateDeviceUpgrade(oldDeviceUpgrade);
		
		// 保存操作日志
		String module = "";
		String keywords = "";
		if ( BusinessConstant.DEVICE_UPGRADE_TYPE_FIRMWARE == oldDeviceUpgrade.getUpgradeType() ) {
			module = ModuleConstant.MODULE_FIRMWARE_MNG;
			keywords = "更新固件：[" +deviceUpgrade.getUpgradeName() + "]";
		} else {
			module = ModuleConstant.MODULE_SOFTWARE_MNG;
			keywords = "更新APK：[" +deviceUpgrade.getUpgradeName() + "]";
		}
		saveLog(operationIp, user, keywords ,module);
	}

	/**
	 * 根据主键查询固件升级信息
	 * hanqr 2018-08-14
	 * @param deviceUpgradeId 主键
	 * @return
	 */
	@Override
	public DeviceUpgradeVO getDeviceUpgradeByIdVo(Long deviceUpgradeId) {
		DeviceUpgrade deviceUpgrade = deviceUpgradeMapper.getDeviceUpgradeById(deviceUpgradeId);
		if(deviceUpgrade != null){
			DeviceUpgradeVO deviceUpgradeVO = new DeviceUpgradeVO();
			BeanUtils.copyProperties(deviceUpgradeVO, deviceUpgrade, true);
			if(StringUtils.isNotBlank(deviceUpgrade.getModelId())) {
				deviceUpgradeVO.setModel(Arrays.asList(deviceUpgrade.getModelId().split(",")));
			}
			return deviceUpgradeVO;
		}
		return null;
	}

	/**
	 * 保存操作日志
	 * @param operationIp 当前操作ip
	 * @param user 当前登录用户
	 * @param keyWords 操作内容
	 * @param module 操作模块
	 */
	private void saveLog(String operationIp, User user, String keyWords, String module) {
		// 保存操作日志
		OperationLog operationLog = new OperationLog();
		operationLog.setOperationContent(keyWords);
		operationLog.setOperationModule(module);
		operationLog.setOperationStatus(BusinessConstant.OPERATION_LONG_OPERATION_STATUS_SUCCESS);
		operationLog.setOperationTime(System.currentTimeMillis());
		operationLog.setUserName(user.getUserName());
		operationLog.setRealname(user.getRealname());
		operationLog.setOperationIp(operationIp);
		operationLogService.saveOperationLog(operationLog);
	}
	
	/**
	 * 保存apk文件(如果要返回文件的下载信息，需要传入下载文件路径和封装分析消息的Map)
	 * @param file  apk文件
	 * @throws IOException
	 */
	@Override
	public Map<Object, Object> saveApkFile(MultipartFile file) throws IOException, ParserException {
		//返回信息Map
		Map<Object, Object> msgMap = Maps.newHashMap();
		//上传文件到华为云,返回文件保存地址
		String fileSaveURL = huaWeiCloudUtils.uploadFile2HuaweiCloud(file, BusinessConstant.FILE_APK_RELATIVE_PATH);
		if (StringUtils.isBlank(fileSaveURL)) {
			throw new ServerException("上传文件到华为云失败");
		}
		//将MultipartFile转为File
		File apkFile = FileUtils.multipartFileConvertFile(file);
		//获取apk信息,自动关闭流
		try (ApkFile apk = new ApkFile(apkFile)) {
			ApkMeta apkMeta = apk.getApkMeta();
			String apkFileMD5 = FileUtils.getFileMD5(apkFile);
			msgMap.put("md5", apkFileMD5);
			msgMap.put("name", apkMeta.getName());
			msgMap.put("versionCode", apkMeta.getVersionCode());
			msgMap.put("versionName", apkMeta.getVersionName());
			double size = file.getSize() / 1024.00 / 1024;
			DecimalFormat decimalFormat  =   new DecimalFormat("##0.00");
			msgMap.put("size", decimalFormat.format(size));
		}
		//删除因MultipartFile转化为File后，创建的本地File文件
		if (apkFile.exists()) {
			apkFile.delete();
		}
		msgMap.put("fileURL", buildPathName(fileSaveURL));
		msgMap.put("filename", file.getOriginalFilename());
		return msgMap;
	}
	
	/**
	 * 保存固件文件
	 * @param files
	 * @return
	 * @throws IOException
	 */
	@Override
	public Map<Object, Object> saveFirmwareFile(MultipartFile files) throws IOException {
		//文件上传
		String fileSaveURL = huaWeiCloudUtils.uploadFile2HuaweiCloud(files, BusinessConstant.FILE_FIRMWARE_RELATIVE_PATH);
		if (StringUtils.isBlank(fileSaveURL)) {
            throw new ServerException("上传固件文件到华为云失败");
		}
		//文件完整路径
		Map<Object, Object> msgMap = Maps.newHashMap();
		//获取文件大小
		double size = files.getSize() / 1024.00 / 1024;
		DecimalFormat decimalFormat  =   new DecimalFormat("##0.00");
		msgMap.put("size", decimalFormat.format(size));
        msgMap.put("fileURL", buildPathName(fileSaveURL));
        msgMap.put("filename", files.getOriginalFilename());
		return msgMap;
	}

	@Override
	public boolean del(Integer softwareUpgradeId,Integer firmwareUpgradeId) {
		int count = deviceSettingMapper.countSettingByUpgradeId(softwareUpgradeId,firmwareUpgradeId);
		if ( count == 0 ) {
			Integer upgradeId = softwareUpgradeId != null ? softwareUpgradeId : firmwareUpgradeId;
			int effect = deviceUpgradeMapper.delById(upgradeId);
			return effect > 0 ;
		}
		return false;
	}

	private String buildPathName(String contextFileName) {
		return contextFileName.toString().replace("\\", "/");
	}


	/**
	 * 升级终端软件版本（仅设置终端升级id）
	 * @param upgradeType     软件升级OR升级固件
	 * @param deviceCodes     终端编码
	 * @param deviceUpgradeId 升级ID
	 * @param user  当前登录用户
	 * @param operationIp 当前操作IP
	 * @throws ServiceException
	 */
	@Override
	@Transactional(readOnly = false, rollbackFor = Exception.class)
	public void deviceUpgrade(Integer upgradeType, String deviceCodes, Long deviceUpgradeId, User user,String operationIp) throws ServiceException {
		DeviceUpgrade deviceUpgrade = deviceUpgradeMapper.getDeviceUpgradeById(deviceUpgradeId);
		if ( deviceUpgrade == null ) {
			throw new ServiceException("升级信息不存在，请检查参数是否正确！");
		}
		List<String> codes = null;
        // 记录批次号（时间戳）保证数据库跟缓存中更新时间一致
		Long serialNo = System.currentTimeMillis();
		String module = "";
		if ( StringUtils.isNotBlank(deviceCodes) ) {
			DeviceSetting setting = new DeviceSetting();
			setting.setUpdateTime(serialNo);
			codes = Arrays.asList(deviceCodes.split(","));
			if (BusinessConstant.DEVICE_UPGRADE_TYPE_SOFTWARE == upgradeType) {
				setting.setSoftwareUpgradeId(deviceUpgradeId);
				module = ModuleConstant.MODULE_SOFTWARE_MNG;
			} else if (BusinessConstant.DEVICE_UPGRADE_TYPE_FIRMWARE == upgradeType){
				setting.setFirmwareUpgradeId(deviceUpgradeId);
				module = ModuleConstant.MODULE_FIRMWARE_MNG;
			}
			deviceSettingMapper.updateDeviceSetting(setting, codes);
		}
		// 保存操作日志
		saveLog( operationIp, user, "设置终端升级信息，升级为：[" + deviceUpgrade.getUpgradeName() + "]",module);
		// 刷新缓存,不影响事务操作
		try {
			DeviceSettingType settingType = (BusinessConstant.DEVICE_UPGRADE_TYPE_SOFTWARE == upgradeType ? DeviceSettingType.SOFTWARE_UPGRADE : DeviceSettingType.FIRMWARE_UPGRADE);
			deviceInfoService.flushDeviceStateCache(settingType, codes, serialNo);
		} catch (Exception e) {
			e.printStackTrace();
			logger.error("设置终端升级信息，更新缓存异常：" + e.getMessage(),e);
		}
	}
}
